#ifndef __SOCKETRECVBUFF_HEADER
#define __SOCKETRECVBUFF_HEADER

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>


struct SockRecvBuff {
	static const int HEADER_SIZE = 16;
	static const int FIELD_SIZE  = 16;
	static const int MAX_RECV_DATA_SIZE = 10100;

	int status;
	int index;
	int length;
	int body_length;
	int remain;
	char *buff;

	SockRecvBuff() {
		status = 0;
		index  = 0;
		length = HEADER_SIZE;
		remain = length;
		buff = new char[HEADER_SIZE+MAX_RECV_DATA_SIZE];
		memset(buff, 0, sizeof(char)*(HEADER_SIZE+MAX_RECV_DATA_SIZE));
	}
	~SockRecvBuff() {
		delete[] buff;
	}

	ssize_t read_header(int fd) {
		while (true) {
			ssize_t n = read(fd, buff+index, remain);
			if (n == -1 || n == 0) return n;
			remain -= n;
			index  += n;
			if (remain == 0) {
				buff[index] = '\0';
				status = 2;
				break;
			}
		}
		return index;
	}
	
	void get_body_length() {
		index = 0;
		sscanf(buff, "%d", &length);
		remain = length;
	}

	ssize_t read_body(int fd) {
		while (true) {
			ssize_t n = read(fd, buff+index, remain);
			if (n == -1) return -1;
			if (n == 0) return 0;
			index += n;
			remain -= n;
			if (remain == 0) {
				status = 2;
				buff[index] = '\0';
				break;
			}
		}
		return index;
	}
	
	ssize_t read_data(int fd) {
		if (!finish_header()) {
			ssize_t n = read_header(fd);
			if (n == -1 || n == 0) return n;
		}	
		if (finish_header()) {
			get_body_length();
			ssize_t n = read_body(fd);
			if (n == -1 || n == 0) return n;
		}
		return index;
	}

	bool finish_header() {
		return status >= 1;
	}
	bool finish_body() {
		return status >= 2;
	}
};

#endif // __SOCKETRECVBUFF_HEADER
